msg_tool\scripts\artemis\ast/
mod.rs1mod dump;
3mod parser;
4mod text;
5mod types;
6
7use crate::scripts::base::*;
8use crate::types::*;
9use crate::utils::encoding::*;
10use anyhow::Result;
11use std::io::Write;
12
13pub use dump::Dumper;
14pub use parser::Parser;
15pub use types::*;
16
17#[derive(Debug)]
18pub struct AstScriptBuilder {}
20
21impl AstScriptBuilder {
22 pub fn new() -> Self {
24 AstScriptBuilder {}
25 }
26}
27
28impl ScriptBuilder for AstScriptBuilder {
29 fn default_encoding(&self) -> Encoding {
30 Encoding::Utf8
31 }
32
33 fn build_script(
34 &self,
35 buf: Vec<u8>,
36 _filename: &str,
37 encoding: Encoding,
38 _archive_encoding: Encoding,
39 config: &ExtraConfig,
40 _archive: Option<&Box<dyn Script>>,
41 ) -> Result<Box<dyn Script>> {
42 Ok(Box::new(AstScript::new(buf, encoding, config)?))
43 }
44
45 fn extensions(&self) -> &'static [&'static str] {
46 &["ast"]
47 }
48
49 fn script_type(&self) -> &'static ScriptType {
50 &ScriptType::Artemis
51 }
52
53 fn is_this_format(&self, _filename: &str, buf: &[u8], buf_len: usize) -> Option<u8> {
54 let parser = parser::Parser::new(&buf[..buf_len], Encoding::Utf8);
55 if parser.try_parse_header().is_ok() {
56 Some(15)
57 } else {
58 None
59 }
60 }
61}
62
63#[derive(Debug)]
64pub struct AstScript {
66 ast: AstFile,
67 indent: Option<usize>,
68 max_line_width: usize,
69 no_indent: bool,
70 lang: Option<String>,
71}
72
73impl AstScript {
74 pub fn new(buf: Vec<u8>, encoding: Encoding, config: &ExtraConfig) -> Result<Self> {
80 let parser = parser::Parser::new(&buf, encoding);
81 let ast = parser.parse()?;
82 Ok(AstScript {
83 ast,
84 indent: config.artemis_indent,
85 max_line_width: config.artemis_max_line_width,
86 no_indent: config.artemis_no_indent,
87 lang: config.artemis_ast_lang.clone(),
88 })
89 }
90}
91
92impl Script for AstScript {
93 fn default_output_script_type(&self) -> OutputScriptType {
94 OutputScriptType::Json
95 }
96
97 fn default_format_type(&self) -> FormatOptions {
98 FormatOptions::None
99 }
100
101 fn extract_messages(&self) -> Result<Vec<Message>> {
102 let mut messages = Vec::new();
103 let ast = &self.ast.ast;
104 let mut lang: Option<&str> = self.lang.as_ref().map(|s| s.as_str());
105 if ast["label"]["top"]["block"].is_null() && ast["text"].is_array() {
107 let text = &ast["text"];
108 let mut text_index = 1i64;
109 for block in ast.members() {
110 if block.is_array() {
111 let savetitle = &block[Key("savetitle")];
112 if savetitle.is_array() {
113 if let Some(lang) = lang {
114 if let Some(title) = savetitle[lang].as_str() {
115 messages.push(Message {
116 name: None,
117 message: title.to_string(),
118 });
119 } else if let Some(title) = savetitle["text"].as_str() {
120 messages.push(Message {
121 name: None,
122 message: title.to_string(),
123 });
124 }
125 } else if let Some(title) = savetitle["text"].as_str() {
126 messages.push(Message {
127 name: None,
128 message: title.to_string(),
129 });
130 }
131 }
132 if !block[Key("text")].is_null() {
133 let tex = &text[NumKey(text_index)];
134 text_index += 1;
135 if tex.is_array() {
136 if tex.arr_len() > 0 {
138 let name = &tex["name"];
139 let nam = if name.is_array() && &name[0] == "name" {
140 if let Some(name) = name["name"].as_string() {
141 Some(name)
142 } else {
143 None
144 }
145 } else {
146 None
147 };
148 for item in tex.members() {
149 if !item.is_array() {
150 continue;
151 }
152 let message = text::TextGenerator::new().generate(item)?;
153 messages.push(Message {
154 name: nam.clone(),
155 message: message
156 .replace("<rt2>", "\n")
157 .replace("<ret2>", "\n"),
158 });
159 }
160 continue;
161 }
162 let lan = match lang {
163 Some(l) => l,
164 None => {
165 for l in tex.kv_keys() {
166 if l.is_str() && l != "vo" && l != "name" {
167 lang = l.as_str();
168 break;
169 }
170 }
171 match lang {
172 Some(l) => l,
173 None => continue,
175 }
176 }
177 };
178 let mut te = &tex[lan];
179 if te.is_null() {
180 for l in tex.kv_keys() {
181 if l != "vo" && l != "name" {
182 te = &tex[l];
183 break;
184 }
185 }
186 }
187 let name = &tex["name"];
188 let nam = if name.is_array() {
189 if let Some(lang) = lang {
190 if let Some(n) = name[lang].as_string() {
191 Some(n)
192 } else if let Some(n) = name["name"].as_string() {
193 Some(n)
194 } else {
195 None
196 }
197 } else if let Some(n) = name["name"].as_string() {
198 Some(n)
199 } else {
200 None
201 }
202 } else if te["name"].is_array() && &te["name"][0] == "name" {
203 if let Some(n) = te["name"]["name"].as_string() {
205 Some(n)
206 } else {
207 None
208 }
209 } else {
210 None
211 };
212 for item in te.members() {
213 if !item.is_array() {
215 continue;
216 }
217 let message = text::TextGenerator::new().generate(item)?;
218 messages.push(Message {
219 name: nam.clone(),
220 message: message.replace("<rt2>", "\n").replace("<ret2>", "\n"),
221 });
222 }
223 }
224 } else if !block[Key("select")].is_null() {
225 let tex = &text[NumKey(text_index)]["select"];
226 text_index += 1;
227 if tex.is_array() {
228 let lan = match lang {
229 Some(l) => l,
230 None => {
231 for l in tex.kv_keys() {
232 if l.is_str() && l != "vo" && l != "name" {
233 lang = l.as_str();
234 break;
235 }
236 }
237 match lang {
238 Some(l) => l,
239 None => continue,
241 }
242 }
243 };
244 let mut te = &tex[lan];
245 if te.is_null() {
246 for l in tex.kv_keys() {
247 if l != "vo" && l != "name" {
248 te = &tex[l];
249 break;
250 }
251 }
252 }
253 for item in te.members() {
254 if let Some(select) = item.as_str() {
255 messages.push(Message {
256 name: None,
257 message: select.to_string(),
258 });
259 }
260 }
261 }
262 }
263 }
264 }
265 return Ok(messages);
266 }
267 let mut block_name = ast["label"]["top"]["block"]
268 .as_str()
269 .ok_or(anyhow::anyhow!("Missing top block name"))?;
270 let mut block = &ast[block_name];
271 loop {
272 let savetitle = &block[Key("savetitle")];
273 if savetitle.is_array() {
274 if let Some(lang) = lang {
275 if let Some(title) = savetitle[lang].as_str() {
276 messages.push(Message {
277 name: None,
278 message: title.to_string(),
279 });
280 } else if let Some(title) = savetitle["text"].as_str() {
281 messages.push(Message {
282 name: None,
283 message: title.to_string(),
284 });
285 }
286 } else if let Some(title) = savetitle["text"].as_str() {
287 messages.push(Message {
288 name: None,
289 message: title.to_string(),
290 });
291 }
292 }
293 let text = &block["text"];
294 if text.is_array() {
295 let lan = match lang {
296 Some(l) => l,
297 None => {
298 for l in text.kv_keys() {
299 if l.is_str() && l != "vo" {
300 lang = l.as_str();
301 break;
302 }
303 }
304 match lang {
305 Some(l) => l,
306 None => {
308 block_name = match block["linknext"].as_str() {
309 Some(name) => name,
310 None => break,
311 };
312 block = &ast[block_name];
313 continue;
314 }
315 }
316 }
317 };
318 let mut tex = &text[lan];
319 if tex.is_null() {
320 for l in text.kv_keys() {
321 if l != "vo" {
322 tex = &text[l];
323 break;
324 }
325 }
326 }
327 for item in tex.members() {
328 let name = item["name"].last_member().as_string();
329 let message = text::TextGenerator::new().generate(item)?;
330 messages.push(Message {
331 name: name,
332 message: message
333 .replace("<rt2>", "\n")
334 .replace("<ret2>", "\n")
335 .trim_end_matches("\n")
336 .to_string(),
337 });
338 }
339 }
340 let select = &block["select"];
341 if select.is_array() {
342 let lan = match lang {
343 Some(l) => l,
344 None => {
345 for l in select.kv_keys() {
346 if l.is_str() && l != "vo" {
347 lang = l.as_str();
348 break;
349 }
350 }
351 match lang {
352 Some(l) => l,
353 None => {
355 block_name = match block["linknext"].as_str() {
356 Some(name) => name,
357 None => break,
358 };
359 block = &ast[block_name];
360 continue;
361 }
362 }
363 }
364 };
365 let mut select_text = &select[lan];
366 if select_text.is_null() {
367 for l in select.kv_keys() {
368 if l != "vo" {
369 select_text = &select[l];
370 break;
371 }
372 }
373 }
374 for item in select_text.members() {
375 if let Some(select) = item.as_str() {
376 messages.push(Message {
377 name: None,
378 message: select.to_string(),
379 });
380 }
381 }
382 }
383 block_name = match block["linknext"].as_str() {
384 Some(name) => name,
385 None => break,
386 };
387 block = &ast[block_name];
388 }
389 Ok(messages)
390 }
391
392 fn import_messages<'a>(
393 &'a self,
394 messages: Vec<Message>,
395 mut file: Box<dyn WriteSeek + 'a>,
396 _filename: &str,
397 encoding: Encoding,
398 replacement: Option<&'a ReplacementTable>,
399 ) -> Result<()> {
400 let mut ast = self.ast.clone();
401 let root = &mut ast.ast;
402 let mut lang = self.lang.as_ref().map(|s| s.to_string());
403 let mut mess = messages.iter();
404 let mut mes = mess.next();
405 if root["label"]["top"]["block"].is_null() && root["text"].is_array() {
406 let mut text_index = 1i64;
407 let len = root.len();
408 for i in 0..len {
409 if root[i].is_array() {
410 if root[i][Key("savetitle")].is_array() {
411 let lan = self.lang.as_ref().map(|s| s.as_str()).unwrap_or("text");
412 let m = match mes {
413 Some(m) => m,
414 None => return Err(anyhow::anyhow!("Not enough messages.")),
415 };
416 let mut title = m.message.clone();
417 if let Some(repl) = replacement {
418 for (k, v) in &repl.map {
419 title = title.replace(k, v);
420 }
421 }
422 root[i][Key("savetitle")][lan].set_string(title);
423 mes = mess.next();
424 }
425 }
426 if !root[i][Key("text")].is_null() {
427 if root["text"][NumKey(text_index)].arr_len() > 0 {
429 let mut arr = Value::new_array();
430 let origin_count = {
431 let text = &root["text"][NumKey(text_index)];
432 let arr_len = text.arr_len();
433 if arr_len < text.len() {
434 for item in text.members() {
435 if !item.is_array() {
436 arr.push_member(item.clone());
438 }
439 }
440 }
441 arr_len
442 };
443 if arr["name"].is_array() && &arr["name"][0] == "name" {
444 let name = match mes {
445 Some(m) => m.name.clone(),
446 None => return Err(anyhow::anyhow!("Message name is missing.")),
447 };
448 let mut name = match name {
449 Some(n) => n,
450 None => return Err(anyhow::anyhow!("Message name is missing.")),
451 };
452 if let Some(repl) = replacement {
453 for (k, v) in &repl.map {
454 name = name.replace(k, v);
455 }
456 }
457 arr["name"]["name"].set_string(name);
458 }
459 for _ in 0..origin_count {
460 let m = match mes {
461 Some(m) => m,
462 None => return Err(anyhow::anyhow!("Not enough messages.")),
463 };
464 let mut text = m.message.clone();
465 if let Some(repl) = replacement {
466 for (k, v) in &repl.map {
467 text = text.replace(k, v);
468 }
469 }
470 let v = text::TextParser::new(&text.replace("\n", "<rt2>")).parse()?;
471 arr.push_member(v);
472 mes = mess.next();
473 }
474 root["text"][NumKey(text_index)] = arr;
475 text_index += 1;
476 continue;
477 }
478 let lan = match &lang {
479 Some(l) => l.as_str(),
480 None => {
481 for l in root["text"][NumKey(text_index)].kv_keys() {
482 if l.is_str() && l != "vo" && l != "name" {
483 lang = l.as_string();
484 break;
485 }
486 }
487 match lang {
488 Some(ref l) => l.as_str(),
489 None => continue,
491 }
492 }
493 };
494 let mut name_find = false;
495 if root["text"][NumKey(text_index)]["name"].is_array() {
496 let name = match mes {
497 Some(m) => m.name.clone(),
498 None => return Err(anyhow::anyhow!("Message name is missing.")),
499 };
500 let mut name = match name {
501 Some(n) => n,
502 None => return Err(anyhow::anyhow!("Message name is missing.")),
503 };
504 if let Some(repl) = replacement {
505 for (k, v) in &repl.map {
506 name = name.replace(k, v);
507 }
508 }
509 let nlan = self.lang.as_ref().map(|s| s.as_str()).unwrap_or("name");
510 root["text"][NumKey(text_index)]["name"][nlan].set_string(name);
511 name_find = true;
512 }
513 let mut arr = Value::new_array();
514 let origin_count = {
515 let text = &root["text"][NumKey(text_index)];
516 let mut tex = &text[lan];
517 if tex.is_null() {
518 for l in text.kv_keys() {
519 if l != "vo" && l != "name" {
520 tex = &text[l];
521 break;
522 }
523 }
524 }
525 let arr_len = tex.arr_len();
526 if arr_len < tex.len() {
527 for item in tex.members() {
528 if !item.is_array() {
529 arr.push_member(item.clone());
531 }
532 }
533 }
534 arr_len
535 };
536 if !name_find && arr["name"].is_array() && &arr["name"][0] == "name" {
537 let name = match mes {
538 Some(m) => m.name.clone(),
539 None => return Err(anyhow::anyhow!("Message name is missing.")),
540 };
541 let mut name = match name {
542 Some(n) => n,
543 None => return Err(anyhow::anyhow!("Message name is missing.")),
544 };
545 if let Some(repl) = replacement {
546 for (k, v) in &repl.map {
547 name = name.replace(k, v);
548 }
549 }
550 arr["name"]["name"].set_string(name);
551 }
552 for _ in 0..origin_count {
553 let m = match mes {
554 Some(m) => m,
555 None => return Err(anyhow::anyhow!("Not enough messages.")),
556 };
557 let mut text = m.message.clone();
558 if let Some(repl) = replacement {
559 for (k, v) in &repl.map {
560 text = text.replace(k, v);
561 }
562 }
563 let v = text::TextParser::new(&text.replace("\n", "<rt2>")).parse()?;
564 arr.push_member(v);
565 mes = mess.next();
566 }
567 root["text"][NumKey(text_index)][lan] = arr;
568 text_index += 1;
569 } else if !root[i][Key("select")].is_null() {
570 let lan = match &lang {
571 Some(l) => l.as_str(),
572 None => {
573 for l in root["text"][NumKey(text_index)]["select"].kv_keys() {
574 if l.is_str() && l != "vo" && l != "name" {
575 lang = l.as_string();
576 break;
577 }
578 }
579 match lang {
580 Some(ref l) => l.as_str(),
581 None => continue,
583 }
584 }
585 };
586 let count = {
587 let text = &root["text"][NumKey(text_index)]["select"];
588 let mut tex = &text[lan];
589 if tex.is_null() {
590 for l in text.kv_keys() {
591 if l != "vo" && l != "name" {
592 tex = &text[l];
593 break;
594 }
595 }
596 }
597 tex.len()
598 };
599 let mut new_select = Value::new_array();
600 for _ in 0..count {
601 let m = match mes {
602 Some(m) => m,
603 None => return Err(anyhow::anyhow!("Not enough messages.")),
604 };
605 let mut select_text = m.message.clone();
606 if let Some(repl) = replacement {
607 for (k, v) in &repl.map {
608 select_text = select_text.replace(k, v);
609 }
610 }
611 new_select.push_member(Value::Str(select_text));
612 mes = mess.next();
613 }
614 root["text"][NumKey(text_index)]["select"][lan] = new_select;
615 text_index += 1;
616 }
617 }
618 if mes.is_some() || mess.next().is_some() {
619 return Err(anyhow::anyhow!("Not all messages were used."));
620 }
621 let mut writer = Vec::new();
622 let mut dumper = dump::Dumper::new(&mut writer);
623 if self.no_indent {
624 dumper.set_no_indent();
625 } else if let Some(indent) = self.indent {
626 dumper.set_indent(indent);
627 }
628 dumper.set_max_line_width(self.max_line_width);
629 dumper.dump(&ast)?;
630 let data = String::from_utf8(writer)?;
631 let encoded = encode_string(encoding, &data, false)?;
632 file.write_all(&encoded)?;
633 file.flush()?;
634 return Ok(());
635 }
636 let mut block_name = root["label"]["top"]["block"]
637 .as_string()
638 .ok_or(anyhow::anyhow!("Missing top block name"))?;
639 let mut block = &mut root[block_name];
640 loop {
641 if block[Key("savetitle")].is_array() {
642 let lan = self.lang.as_ref().map(|s| s.as_str()).unwrap_or("text");
643 let m = match mes {
644 Some(m) => m,
645 None => return Err(anyhow::anyhow!("Not enough messages.")),
646 };
647 let mut title = m.message.clone();
648 if let Some(repl) = replacement {
649 for (k, v) in &repl.map {
650 title = title.replace(k, v);
651 }
652 }
653 block[Key("savetitle")][lan].set_string(title);
654 mes = mess.next();
655 }
656 if block["text"].is_array() {
657 let lan = match &lang {
658 Some(l) => l.as_str(),
659 None => {
660 for l in block["text"].kv_keys() {
661 if l.is_str() && l != "vo" {
662 lang = l.as_string();
663 break;
664 }
665 }
666 match lang {
667 Some(ref l) => l.as_str(),
668 None => {
670 block_name = match block["linknext"].as_string() {
671 Some(name) => name,
672 None => break,
673 };
674 block = &mut root[block_name];
675 continue;
676 }
677 }
678 }
679 };
680 let origin_names: Vec<_> = {
681 let mut tex = &block["text"][lan];
682 if tex.is_null() {
683 for l in block["text"].kv_keys() {
684 if l != "vo" {
685 tex = &block["text"][l];
686 break;
687 }
688 }
689 }
690 tex.members().map(|m| m["name"].clone()).collect()
691 };
692 let mut arr = Value::new_array();
693 for name in origin_names {
694 let m = match mes {
695 Some(m) => m,
696 None => return Err(anyhow::anyhow!("Not enough messages.")),
697 };
698 let mut text = m.message.clone();
699 if let Some(repl) = replacement {
700 for (k, v) in &repl.map {
701 text = text.replace(k, v);
702 }
703 }
704 if !text.ends_with("\n") {
705 text.push('\n');
706 }
707 let mut v = text::TextParser::new(&text.replace("\n", "<rt2>")).parse()?;
708 if name.is_array() {
709 let mut n = match &m.name {
710 Some(n) => n.to_string(),
711 None => return Err(anyhow::anyhow!("Message name is missing.")),
712 };
713 if let Some(repl) = replacement {
714 for (k, v) in &repl.map {
715 n = n.replace(k, v);
716 }
717 }
718 v.insert_member(0, Value::new_kv("name", name));
719 if v["name"].len() <= 1 {
720 if v["name"][0] != n {
721 v["name"].push_member(Value::Str(n));
722 }
723 } else {
724 v["name"].last_member_mut().set_string(n);
725 }
726 }
727 arr.push_member(v);
728 mes = mess.next();
729 }
730 block["text"][lan] = arr;
731 }
732 if block["select"].is_array() {
733 let lan = match &lang {
734 Some(l) => l.as_str(),
735 None => {
736 for l in block["select"].kv_keys() {
737 if l.is_str() && l != "vo" {
738 lang = l.as_string();
739 break;
740 }
741 }
742 match lang {
743 Some(ref l) => l.as_str(),
744 None => {
746 block_name = match block["linknext"].as_string() {
747 Some(name) => name,
748 None => break,
749 };
750 block = &mut root[block_name];
751 continue;
752 }
753 }
754 }
755 };
756 let select_count = {
757 let mut select = &block["select"][lan];
758 if select.is_null() {
759 for l in block["select"].kv_keys() {
760 if l != "vo" {
761 select = &block["select"][l];
762 break;
763 }
764 }
765 }
766 select.len()
767 };
768 let mut new_select = Value::new_array();
769 for _ in 0..select_count {
770 let m = match mes {
771 Some(m) => m,
772 None => return Err(anyhow::anyhow!("Not enough messages.")),
773 };
774 let mut select_text = m.message.clone();
775 if let Some(repl) = replacement {
776 for (k, v) in &repl.map {
777 select_text = select_text.replace(k, v);
778 }
779 }
780 new_select.push_member(Value::Str(select_text));
781 mes = mess.next();
782 }
783 block["select"][lan] = new_select;
784 }
785 block_name = match block["linknext"].as_string() {
786 Some(name) => name,
787 None => break,
788 };
789 block = &mut root[block_name];
790 }
791 if mes.is_some() || mess.next().is_some() {
792 return Err(anyhow::anyhow!("Not all messages were used."));
793 }
794 let mut writer = Vec::new();
795 let mut dumper = dump::Dumper::new(&mut writer);
796 if self.no_indent {
797 dumper.set_no_indent();
798 } else if let Some(indent) = self.indent {
799 dumper.set_indent(indent);
800 }
801 dumper.set_max_line_width(self.max_line_width);
802 dumper.dump(&ast)?;
803 let data = String::from_utf8(writer)?;
804 let encoded = encode_string(encoding, &data, false)?;
805 file.write_all(&encoded)?;
806 file.flush()?;
807 Ok(())
808 }
809}
810
811pub fn is_this_format(_filename: &str, buf: &[u8], buf_len: usize) -> bool {
817 let parser = parser::Parser::new(&buf[..buf_len], Encoding::Utf8);
818 parser.try_parse_header().is_ok()
819}